Skip to content

release: prepare sealed six-file evidence set - #64

Draft
seonghobae wants to merge 15 commits into
security/canonical-forbidden-rootfrom
release/sealed-evidence-preparation
Draft

release: prepare sealed six-file evidence set#64
seonghobae wants to merge 15 commits into
security/canonical-forbidden-rootfrom
release/sealed-evidence-preparation

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Test-first credential-free release-evidence preparation

Progresses #63 without modifying .github, workflow permissions, credentials, protected refs, release identities, dependencies, or files owned by the stacked base PR.

Exact tree binding

PR #62 advanced after this stack was verified. No rebase, retarget, force update, automatic conflict strategy, or credential-bearing publication has been used to hide that divergence. This PR therefore remains draft until an auditable credential-separated integration mechanism reconstructs the intended tree against an accepted #62 head and independently verifies that exact result.

Implemented bounded slice

  • selects exactly one canonical wheel and one matching source distribution and rejects stale, extra, nested, symlinked, non-regular, malformed, mismatched, or oversized inputs;
  • preflights both selected archives before loading the generator or any ZIP/tar parser and binds accepted device, inode, and finite size;
  • reopens each archive with no-follow semantics, requires descriptor and pathname identity to equal the accepted preflight, and copies only bounded bytes into a fresh owner-only parser-only snapshot;
  • delegates ZIP/tar parsing only to the private snapshot, so post-preflight pathname replacement cannot redirect parser work to an alternate or oversized archive;
  • rechecks accepted descriptor/path identity after each copy and retains later descriptor-bound hashing, archive-member validation, SBOM semantics, checksum reconstruction, and final complete-set verification as defense in depth;
  • generates paired deterministic CycloneDX 1.7 SBOMs, canonical SOURCE_IDENTITY.json, and filename-sorted SHA256SUMS without clocks, randomness, runner-local paths, network access, or credentials;
  • exclusively creates owner-only generated files and a separately stored handoff, then independently rebuilds and verifies the complete published set;
  • documents the exact trust boundary, residual mutable-local-storage limitation, explicit non-provenance and no-SLSA-claim boundaries, retry procedure, and APA 7 primary-source references;
  • updates [Unreleased] without a version bump;
  • contains no model, signing, attestation, publication, release, tag, ref, repository-write, OIDC, workflow, dependency, or credential behavior.

Test-first evidence

Exact RED head 2de4bd093014e164b73f0fd61dd4cc414f44d69c replaced the accepted wheel pathname after preflight and proved the former implementation could still reach the delegated generator. The bounded implementation refuses the replacement before parser execution; the regression records no parser input and creates no generated evidence or handoff.

An intermediate exact-head run 31104830261 failed only because the regression expected the generic unsafe error while the implementation correctly rejected the oversized replacement through the stable safety-bound error. Commit b33e424957e4eb38642e79f91c60e93bdaf9a75d narrowed the test to accept either valid fail-closed outcome without weakening the no-parser assertion.

Historical exact-head evidence

CI run 31105569311 succeeded on exact PR #64 head 961abb78b9df1fd3dba0dd23582c8379d845556c:

  • Python 3.10–3.13: success;
  • Ruff, compileall, and product-guard self-test: success;
  • 751 tests: success;
  • production coverage: 1,626 statements and 554 branches, 100%;
  • wheel and source-distribution package acceptance: success.

That evidence validates this exact branch head only against its historical stacked base. It is not evidence for a future reconstructed tree incorporating current #62. Applicable SAST and Security Scan evidence also remains required for the integrated exact tree.

Remaining gates

Keep this PR draft. Require accepted #62 integration first, an auditable credential-separated reconstruction with stale-head refusal, then exact integrated-tree CI, Python 3.10–3.13, 100% production statement/branch coverage, package acceptance, automated review, applicable SAST/Security Scan, independent non-author approval, branch protection, and every repository policy gate.

Do not merge, enable auto-merge, mark ready, release, publish, rebase, retarget, force-update, or claim provenance or a SLSA Build level.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1d766bcc-0623-4742-959a-008c8996c667

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Apply the bounded documentation/changelog completion to exact current head f114369889211f6f53715699a878ea3a701772d8 on branch release/sealed-evidence-preparation.

Current exact-head implementation and tests already exist in:

  • scripts/ci/prepare_release_evidence.py
  • tests/test_prepare_release_evidence.py
  • docs/release-evidence-preparation.md

Modify only:

  • CHANGELOG.md
  • docs/release.md

Required changes:

  1. Add one concise [Unreleased]Added entry describing the credential-free preparer: exact wheel/sdist cardinality, paired deterministic CycloneDX 1.7 SBOMs, canonical source identity, filename-sorted checksums, owner-only exclusive outputs, separately stored handoff, and independent post-publication re-verification. Do not imply hosted provenance or a SLSA level.
  2. In docs/release.md, add a short subsection after local package acceptance that links release-evidence-preparation.md, states that the preparer runs only in a read-only credential-free exact-SHA checkout after acceptance, and makes clear that current branch-local work does not modify or weaken the credential-bearing release workflow. Do not rewrite current publish behavior as already integrated.
  3. Preserve existing APA 7 references and claims. Do not add a version bump.

Do not modify .github, workflows, scripts, tests, package code, dependencies, permissions, protected refs, credentials, review-agent identities, release/tag behavior, or any other path. Do not merge, release, publish, mark ready, or enable auto-merge. Stop if the exact head has changed before applying the two-file edit.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Supersede the earlier docs-only request and apply this bounded test-first hardening to exact current head f114369889211f6f53715699a878ea3a701772d8 on branch release/sealed-evidence-preparation.

A valid resource-bound gap remains: prepare_release_evidence(...) passes the selected wheel and source distribution to the archive/SBOM parser before enforcing MAX_DISTRIBUTION_BYTES. The current bound is first applied later while checksums are computed, so an oversized untrusted archive can consume parser CPU/memory before the preparer rejects it. This contradicts the preparer's stated finite-input trust boundary.

Use an immutable RED commit first, then GREEN:

  1. Add a focused regression in tests/test_prepare_release_evidence.py that creates an exact-name oversized sparse distribution (MAX_DISTRIBUTION_BYTES + 1), monkeypatches _load_attestable_generator to fail if invoked, and proves the preparer rejects the archive before loading or executing the generator and before creating any SBOM, source-identity, checksum, or handoff output.
  2. Add a beginner-readable private preflight helper in scripts/ci/prepare_release_evidence.py that validates each selected distribution's current regular-file metadata and finite byte size before _load_attestable_generator() or any archive parsing. Normalize filesystem failures and reject values above MAX_DISTRIBUTION_BYTES; retain later descriptor-bound hashing and final verifier checks as defense in depth.
  3. Apply the preflight to both wheel and sdist immediately after exact cardinality/version selection. Do not weaken or remove existing descriptor/path identity, checksum, post-publication, or retry semantics.
  4. Complete the already-pending documentation work:
    • add the concise [Unreleased]Added entry in CHANGELOG.md for the credential-free six-file preparer without claiming hosted provenance or a SLSA level;
    • add the short post-acceptance subsection in docs/release.md linking release-evidence-preparation.md and preserving the current credential-bearing workflow boundary;
    • update docs/release-evidence-preparation.md to state that compressed distribution byte bounds are enforced before archive parsing and that archive/member semantic checks remain separate.
  5. Run the focused RED/GREEN test, complete Python 3.10–3.13 suite, Ruff, compileall, public-docstring checks, 100% production statement and branch coverage, package acceptance, SAST, and Security Scan on the resulting exact head.

Modify only:

  • tests/test_prepare_release_evidence.py
  • scripts/ci/prepare_release_evidence.py
  • docs/release-evidence-preparation.md
  • docs/release.md
  • CHANGELOG.md

Do not modify .github, workflows, dependencies, permissions, credentials, protected refs, release/tag behavior, review-agent identities, or any other path. Do not merge, mark ready, enable auto-merge, publish, release, or bump the version. Stop without writing if the exact head changed before the RED commit.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Review only exact current stacked head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 against exact base 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657. Prior draft-skip notices and requests naming earlier heads are superseded. Focus on finite archive-byte preflight before generator/archive parsing, descriptor/path identity, exclusive owner-only outputs, strict deterministic JSON, canonical source and checksum binding, post-publication independent reconstruction, failure cleanup semantics, explicit non-provenance/SLSA boundaries, APA 7 references, and the absence of credentials, network, workflow, ref, tag, release, attestation, or publication behavior. Do not approve, merge, rebase, retarget, publish, or treat the successful CI as a substitute for stacked-base security scans and independent approval.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

@seonghobae I will review the exact requested stacked range from 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657 to 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4.

I will not approve, merge, rebase, retarget, publish, or release. I will treat the successful CI result as separate from the required stacked-base security scans and independent approval.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Review only exact current stacked head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 against exact base 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657. Prior rate-limited requests and requests naming earlier heads are superseded. Focus on archive-byte preflight before generator/archive parsing, exact wheel/sdist cardinality and version binding, descriptor/path identity, strict deterministic outputs, owner-only exclusive publication, complete post-publication reconstruction, failure cleanup guidance, non-provenance/SLSA claim boundaries, APA 7 references, and absence of credentials/network/workflow/ref/tag/release behavior. Do not approve, merge, publish, release, rebase, or retarget.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

@seonghobae I will review only the requested stacked range from 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657 to 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4.

I will focus on the specified archive preflight, identity binding, deterministic and owner-only outputs, reconstruction, documentation boundaries, and prohibited behavior. I will not approve, merge, publish, release, rebase, or retarget.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Perform a complete static review of exact current head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 against exact stacked base 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657. Earlier rate-limited output is incomplete and must not be treated as review success.

Focus on the credential-free release-evidence boundary: exactly one canonical wheel and one matching source distribution; rejection of stale, extra, nested, symlinked, non-regular, malformed, mismatched, or oversized inputs before generator loading and archive parsing; deterministic CycloneDX 1.7 SBOMs; canonical source identity and filename-sorted checksums; exclusive owner-only outputs and separately stored handoff; post-publication independent reconstruction; exact repository/source binding; and preservation of existing member, metadata, digest, path, and mutable-storage defenses. Confirm there is no network, credential, model, signing, attestation, publication, release, tag, ref, repository-write, OIDC, dependency, or workflow behavior, and that documentation, APA 7 references, and CHANGELOG claims match the implementation. Do not approve, merge, retarget, rebase, mark ready, publish, or infer success from CI alone.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='13cd59b5d0307f1a4dc1e4ffe777ed31b878c657'
head='421c0975cdabbc24cb4c42a9bb11e202cd33b0a4'

printf '%s\n' '== Exact commit verification =='
git rev-parse "${base}^{commit}"
git rev-parse "${head}^{commit}"
git merge-base --is-ancestor "$base" "$head"
printf 'base_is_ancestor=true\n'

printf '%s\n' '== Changed files =='
git diff --name-status "$base" "$head"
printf '%s\n' '== Diff summary =='
git diff --stat "$base" "$head"

printf '%s\n' '== Implementation outline =='
ast-grep outline scripts/ci/prepare_release_evidence.py --items all || true
printf '%s\n' '== Test outline =='
ast-grep outline tests/test_prepare_release_evidence.py --items all || true

printf '%s\n' '== Security-relevant definitions and calls =='
rg -n -C 4 \
  '^(def |class )|MAX_DISTRIBUTION_BYTES|_load_attestable_generator|stat\(|lstat\(|open\(|os\.open|chmod|mkdir|unlink|rmtree|replace|rename|sha256|tarfile|zipfile|json\.|subprocess|urlopen|requests|http|socket|oidc|credential|token|sign|attest|publish|release|git ' \
  scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py || true

printf '%s\n' '== Exact range prohibited-behavior scan =='
git diff --unified=3 "$base" "$head" -- \
  ':!scripts/ci/prepare_release_evidence.py' ':!tests/test_prepare_release_evidence.py' \
  | rg -n -i -C 2 'https?://|requests|urllib|socket|subprocess|os\.system|github|oidc|credential|token|secret|sign|attest|publish|release|git (tag|push|commit|checkout|reset)|workflow|\.github' || true

printf '%s\n' '== Full diff for reviewed files =='
git diff --find-renames --find-copies --unified=80 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py \
  tests/test_prepare_release_evidence.py \
  docs/release-evidence-preparation.md \
  docs/release.md \
  CHANGELOG.md

Length of output: 100571


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Locate delegated implementation and tests =='
fd -a 'generate_attestable_release_sbom\.py|release_evidence\.py|test_release_sbom\.py|test_release_evidence.*\.py' . \
  -E .git -E node_modules -E dist -E build

printf '%s\n' '== Delegated implementation outlines =='
ast-grep outline scripts/ci/generate_attestable_release_sbom.py --items all || true
ast-grep outline src/egressweave/release_evidence.py --items all || true

printf '%s\n' '== Generator archive and input handling =='
rg -n -C 8 \
  '^(def |class )|build_attestable_sbom|ZipFile|TarFile|tarfile|zipfile|open\(|lstat\(|fstat\(|stat\(|resolve\(|sha256|MAX_|member|extract|subprocess|urlopen|requests|socket' \
  scripts/ci/generate_attestable_release_sbom.py || true

printf '%s\n' '== Verifier creation, reconstruction, and mutable-storage handling =='
rg -n -C 10 \
  '^(def |class )|build_evidence_manifest|write_evidence_manifest|_require_post_publication_state|open\(|os\.open|lstat\(|fstat\(|stat\(|fsync|chmod|O_NOFOLLOW|O_EXCL|resolve\(|is_relative_to|sha256|MAX_|ZipFile|TarFile|tarfile|zipfile|subprocess|urlopen|requests|socket' \
  src/egressweave/release_evidence.py || true

printf '%s\n' '== Relevant existing test definitions =='
ast-grep outline tests/test_release_sbom.py --items all || true
fd -a -t f 'test*release*evidence*.py' tests -x sh -c \
  'echo "== $1 =="; ast-grep outline "$1" --items all' sh {} \; || true

printf '%s\n' '== Entire requested range: imports and invoked external interfaces =='
git diff --unified=0 \
  13cd59b5d0307f1a4dc1e4ffe777ed31b878c657 \
  421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 \
  -- scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py \
  | rg -n '^\+.*\b(import|from|subprocess|socket|requests|urllib|http|open|exec|eval|system|popen|run|check_call|check_output|git|token|credential|secret|oidc|sign|attest|publish|release)\b' || true

Length of output: 44676


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Locate foundation generator =='
fd -a '^generate_release_sbom\.py$' scripts

printf '%s\n' '== Foundation generator outline =='
ast-grep outline scripts/ci/generate_release_sbom.py --items all

printf '%s\n' '== Foundation generator: archive parsing and artifact digest code =='
rg -n -C 12 \
  '^(def |class )|build_sbom|ZipFile|TarFile|tarfile|zipfile|artifact_path|open\(|lstat\(|fstat\(|stat\(|sha256|MAX_|metadata|extract|read\(' \
  scripts/ci/generate_release_sbom.py

printf '%s\n' '== Exact source slices for the preparer boundary =='
nl -ba scripts/ci/prepare_release_evidence.py | sed -n '90,215p'
nl -ba scripts/ci/prepare_release_evidence.py | sed -n '258,360p'

printf '%s\n' '== Generator call chain around artifact handling =='
nl -ba scripts/ci/generate_attestable_release_sbom.py | sed -n '175,200p'
nl -ba scripts/ci/generate_release_sbom.py | sed -n '1,360p'

printf '%s\n' '== Existing tests for replacement, descriptor identity, and generator input size =='
rg -n -i -C 5 \
  'replace|rename|symlink|descriptor|inode|fstat|lstat|mutable|concurrent|race|oversized|MAX_ARTIFACT_BYTES|preflight' \
  tests scripts/ci/generate_release_sbom.py scripts/ci/prepare_release_evidence.py

Length of output: 25640


@seonghobae I completed a static review of the verified range from 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657 to 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4.

I found one issue.

  • High — Bind the preflighted archive before archive parsing. scripts/ci/prepare_release_evidence.py preflights each path with lstat() at Lines 124-133, but it passes the path by name to the generator at Lines 298-311. The delegated foundation generator then opens that pathname with zipfile.ZipFile(path) or tarfile.open(path, mode="r:gz"). It does not bind the opened archive descriptor to the preflighted file identity or reapply the compressed-byte bound before parsing. A concurrent local writer can replace a valid selected archive after preflight with another regular file that has the same filename. The parser can then consume the replacement before the later verifier rejects the evidence. This bypasses the stated finite pre-parser trust boundary. Open each selected archive through a no-follow descriptor, verify its device/inode and bounded size immediately before parsing, and parse that bound descriptor or an immutable verified snapshot. Add a replacement-race regression test.

The range adds no direct network, credential, OIDC, workflow, repository-write, ref/tag, signing, attestation, publication, or release behavior. The documentation and changelog accurately state the credential-free and non-provenance/SLSA boundaries. I did not approve the pull request.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Perform a complete static review of exact current stacked head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 against exact base 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657. Every earlier rate-limited or queued response is incomplete and superseded. Review the full five-file diff for exact wheel/sdist cardinality and version binding, rejection of stale/extra/nested/symlinked/non-regular/malformed/mismatched/oversized archives before parser loading, descriptor/path identity, deterministic CycloneDX 1.7 outputs, canonical source identity and sorted checksums, owner-only exclusive outputs, separately stored handoff, post-publication reconstruction, failure cleanup, explicit non-provenance/SLSA boundaries, APA 7 references, CHANGELOG accuracy, and absence of credentials, network, workflow, repository-write, OIDC, signing, attestation, tag, release, or publication behavior. Do not approve, merge, rebase, retarget, mark ready, publish, or infer success from CI alone.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='13cd59b5d0307f1a4dc1e4ffe777ed31b878c657'
head='421c0975cdabbc24cb4c42a9bb11e202cd33b0a4'

printf '%s\n' '== Exact range =='
git rev-parse "${base}^{commit}"
git rev-parse "${head}^{commit}"
git merge-base --is-ancestor "$base" "$head"
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"

printf '%s\n' '== Full five-file diff =='
git diff --find-renames --find-copies --unified=100 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py \
  tests/test_prepare_release_evidence.py \
  docs/release-evidence-preparation.md \
  docs/release.md \
  CHANGELOG.md

printf '%s\n' '== Preparer outline and relevant source =='
ast-grep outline scripts/ci/prepare_release_evidence.py --items all
nl -ba scripts/ci/prepare_release_evidence.py | sed -n '1,430p'

printf '%s\n' '== Test outline and relevant source =='
ast-grep outline tests/test_prepare_release_evidence.py --items all
nl -ba tests/test_prepare_release_evidence.py | sed -n '1,520p'

printf '%s\n' '== Locate and map repository-local generator/verifier =='
fd -a -t f 'generate_attestable_release_sbom.py|generate_release_sbom.py|release_evidence.py' . \
  -E .git -E node_modules -E dist -E build
ast-grep outline scripts/ci/generate_attestable_release_sbom.py --items all || true
ast-grep outline scripts/ci/generate_release_sbom.py --items all || true
ast-grep outline src/egressweave/release_evidence.py --items all || true

printf '%s\n' '== Generator and verifier security-critical call chains =='
rg -n -C 8 \
  '^(def |class )|build_attestable_sbom|build_sbom|ZipFile|tarfile\.open|TarFile|lstat\(|fstat\(|stat\(|os\.open|O_NOFOLLOW|O_EXCL|open\(|sha256|MAX_|member|artifact|manifest|reconstruct|post_publication|chmod|unlink|rmtree|replace|rename' \
  scripts/ci/generate_attestable_release_sbom.py \
  scripts/ci/generate_release_sbom.py \
  src/egressweave/release_evidence.py || true

printf '%s\n' '== Changed-range prohibited behavior scan =='
git diff --unified=3 "$base" "$head" | rg -n -i -C 2 \
  'https?://|urllib|requests|socket|subprocess|os\.system|popen|oidc|credential|token|secret|sign|attest|publish|git (tag|push|commit|checkout|reset)|workflow|\.github|release|ref' || true

printf '%s\n' '== Documentation and changelog in current head =='
nl -ba docs/release-evidence-preparation.md | sed -n '1,360p'
nl -ba docs/release.md | sed -n '1,360p'
nl -ba CHANGELOG.md | sed -n '1,180p'

Length of output: 52899


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='13cd59b5d0307f1a4dc1e4ffe777ed31b878c657'
head='421c0975cdabbc24cb4c42a9bb11e202cd33b0a4'

printf '%s\n' '== Confirm requested ancestry =='
if git merge-base --is-ancestor "$base" "$head"; then
  printf '%s\n' 'base_is_ancestor=true'
fi

printf '%s\n' '== Entire preparer =='
sed -n '1,430p' scripts/ci/prepare_release_evidence.py

printf '%s\n' '== Entire preparer tests =='
sed -n '1,520p' tests/test_prepare_release_evidence.py

printf '%s\n' '== Candidate generator and verifier files =='
fd -a -t f . scripts src | grep -E '(^|/)(generate_attestable_release_sbom|generate_release_sbom|release_evidence)\.py$' || true

printf '%s\n' '== Generator and verifier outlines =='
ast-grep outline scripts/ci/generate_attestable_release_sbom.py --items all || true
ast-grep outline scripts/ci/generate_release_sbom.py --items all || true
ast-grep outline src/egressweave/release_evidence.py --items all || true

printf '%s\n' '== Archive opening and artifact identity call sites =='
grep -nE -C 10 \
  'ZipFile|tarfile\.open|TarFile|build_attestable_sbom|build_sbom|artifact_path|lstat\(|fstat\(|os\.open|O_NOFOLLOW|MAX_ARTIFACT_BYTES|MAX_DISTRIBUTION_BYTES|stream' \
  scripts/ci/generate_attestable_release_sbom.py \
  scripts/ci/generate_release_sbom.py \
  src/egressweave/release_evidence.py || true

printf '%s\n' '== Full generator and verifier source =='
sed -n '1,460p' scripts/ci/generate_attestable_release_sbom.py || true
sed -n '1,460p' scripts/ci/generate_release_sbom.py || true
sed -n '1,620p' src/egressweave/release_evidence.py || true

printf '%s\n' '== Changed code imports and external-effect indicators =='
git diff --unified=0 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py \
  | grep -nE '^\+.*\b(import|from|subprocess|requests|urllib|socket|http|OIDC|oidc|credential|token|secret|sign|attest|publish|release|git|os\.system|popen)\b' || true

printf '%s\n' '== Diff file list and documentation references =='
git diff --name-only "$base" "$head"
grep -nE -C 3 'SLSA|provenance|byte|parser|credential|handoff|CycloneDX|Reference|References' \
  docs/release-evidence-preparation.md docs/release.md CHANGELOG.md || true

Length of output: 149063


@seonghobae I completed a static review of exact head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 against exact base 13cd59b5d0307f1a4dc1e4ffe777ed31b878c657.

I found one high-severity issue.

  • High — Bind each preflighted archive to the archive parser. scripts/ci/prepare_release_evidence.py checks only pathname metadata in _require_distribution_preflight() at Lines 124-133. It later passes the mutable paths to generator.build_attestable_sbom() at Lines 304-316. The delegated generator opens these paths anew with zipfile.ZipFile(path) and tarfile.open(path, mode="r:gz"). A concurrent local writer can replace a valid preflighted archive with an oversized regular file of the same canonical filename after preflight and before parser open. The ZIP or tar parser can then process the replacement before the later descriptor-bound checksum and verifier checks reject it. This violates the documented finite pre-parser input boundary. Open each archive through a no-follow descriptor, verify regular-file identity and byte limit immediately before parsing, and parse that bound descriptor or an immutable verified snapshot. Add a regression that replaces an archive after preflight and proves the parser is not invoked on the replacement.

The exact range changes only the requested five files.

I found no added direct network, credential, workflow, repository-write, OIDC, signing, attestation, tag, release, or publication behavior in those files.

The static implementation otherwise matches the reviewed claims for cardinality and version binding, deterministic CycloneDX 1.7 documents, canonical source identity, filename-sorted checksums, exclusive owner-only output creation, external handoff storage, post-publication reconstruction, failure guidance, non-provenance and SLSA boundaries, APA references, and changelog wording.

I did not approve, merge, rebase, retarget, publish, or release this pull request.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Review only exact current head fb54b615cbc69ef92c3ac787db1f3faafbc2cba9 against exact stacked base 6a8f57c29c9ebb561c771829ba75501ba9a91eb8. Earlier draft-skip output and reviews of 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 are not exact-current-head review success.

Focus on exact-one wheel/sdist selection; rejection of stale, extra, nested, symlinked, non-regular, malformed, mismatched, or oversized inputs before generator/parser loading; descriptor-bound hashing and archive/member validation; deterministic CycloneDX 1.7 SBOMs, SOURCE_IDENTITY.json, and sorted SHA256SUMS; owner-only exclusive publication; verifier and handoff reconstruction; exact-source and credential-separation documentation; explicit non-provenance/no-SLSA boundary; APA 7 primary references; and absence of workflow, credential, permission, network, signing, attestation, release, tag, ref, repository-write, OIDC, or publication behavior. Verify the two-parent stack-sync commit imports only the deterministic parser-recursion test from the current base and leaves the PR diff at five intended files. Exact-head CI 31103441012 passed Python 3.10–3.13, Ruff, 750 tests, 1,626 statements/554 branches at 100% production coverage, compileall, product-guard self-test, and wheel/sdist acceptance. Do not approve, merge, mark ready, rebase, retarget, release, publish, or infer success from queued checks.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Review only exact current head fb54b615cbc69ef92c3ac787db1f3faafbc2cba9 against exact stacked base 6a8f57c29c9ebb561c771829ba75501ba9a91eb8; do not modify the branch.

The current two-parent merge synchronizes the prior bounded implementation head 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 with the current PR #62 base and imports only its deterministic strict-JSON parser-recursion test. Exact-head CI 31103441012 succeeded with 750 tests, Python 3.10–3.13, Ruff, compileall, product-guard self-test, wheel/sdist acceptance, and 1,626 statements/554 branches at 100% production coverage.

Independently review exact artifact selection, compressed-byte preflight before generator/parser loading, descriptor-bound hashing, archive/member and SBOM semantics, deterministic six-file evidence, owner-only exclusive creation, verifier and handoff reconstruction, documentation and APA references, explicit non-provenance/no-SLSA boundary, and absence of workflow, credential, permission, network, signing, attestation, release, tag, ref, repository-write, OIDC, or publication behavior. Submit a current-head review outcome only after checking the exact tree and evidence. Keep the PR draft; do not merge, mark ready, enable auto-merge, release, publish, rebase, or retarget.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='6a8f57c29c9ebb561c771829ba75501ba9a91eb8'
head='fb54b615cbc69ef92c3ac787db1f3faafbc2cba9'
first_parent='421c0975cdabbc24cb4c42a9bb11e202cd33b0a4'

printf '%s\n' '== Exact topology =='
git rev-parse "${base}^{commit}"
git rev-parse "${head}^{commit}"
git cat-file -p "$head" | sed -n '1,8p'
git merge-base --is-ancestor "$base" "$head" && echo 'base_is_ancestor=true'
printf '%s\n' '== Parent diffs =='
git diff --name-status "${head}^1" "$head"
git diff --name-status "${head}^2" "$head"
printf '%s\n' '== Requested base-to-head diff =='
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"
printf '%s\n' '== Merge import diff =='
git diff --find-renames --find-copies --unified=20 "${head}^1" "$head"

printf '%s\n' '== Target outlines =='
ast-grep outline scripts/ci/prepare_release_evidence.py --items all
ast-grep outline tests/test_prepare_release_evidence.py --items all
ast-grep outline scripts/ci/generate_attestable_release_sbom.py --items all
ast-grep outline scripts/ci/generate_release_sbom.py --items all
ast-grep outline src/egressweave/release_evidence.py --items all

printf '%s\n' '== Preparer and test critical sections =='
nl -ba scripts/ci/prepare_release_evidence.py | sed -n '1,430p'
nl -ba tests/test_prepare_release_evidence.py | sed -n '1,560p'

printf '%s\n' '== Generator/verifier parser and identity call chains =='
rg -n -C 10 \
  '^(def |class )|build_attestable_sbom|build_sbom|ZipFile|tarfile\.open|TarFile|lstat\(|fstat\(|stat\(|os\.open|O_NOFOLLOW|O_EXCL|MAX_|artifact_path|sha256|member|reconstruct|post_publication|handoff|chmod|unlink|rmtree|replace|rename' \
  scripts/ci/generate_attestable_release_sbom.py \
  scripts/ci/generate_release_sbom.py \
  src/egressweave/release_evidence.py

printf '%s\n' '== Full five-file diff =='
git diff --find-renames --find-copies --unified=60 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py \
  tests/test_prepare_release_evidence.py \
  docs/release-evidence-preparation.md \
  docs/release.md \
  CHANGELOG.md

printf '%s\n' '== Changed-range external-effect indicators =='
git diff --unified=0 "$base" "$head" | rg -n -i -C 2 \
  '^\+.*\b(https?://|urllib|requests|socket|subprocess|os\.system|popen|oidc|credential|token|secret|sign|attest|publish|git\s+(tag|push|commit|checkout|reset)|workflow|\.github|release|ref)\b' || true

printf '%s\n' '== Current documentation and changelog claims =='
rg -n -C 4 \
  'preflight|byte|parser|credential|exact SHA|SLSA|provenance|CycloneDX|SOURCE_IDENTITY|SHA256SUMS|handoff|References|Unreleased' \
  docs/release-evidence-preparation.md docs/release.md CHANGELOG.md

Length of output: 15534


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='6a8f57c29c9ebb561c771829ba75501ba9a91eb8'
head='fb54b615cbc69ef92c3ac787db1f3faafbc2cba9'

printf '%s\n' '== Preparer =='
sed -n '1,430p' scripts/ci/prepare_release_evidence.py

printf '%s\n' '== Preparer tests =='
sed -n '1,560p' tests/test_prepare_release_evidence.py

printf '%s\n' '== Attestable generator =='
sed -n '1,260p' scripts/ci/generate_attestable_release_sbom.py

printf '%s\n' '== Foundation generator archive handling =='
sed -n '1,175p' scripts/ci/generate_release_sbom.py
sed -n '360,510p' scripts/ci/generate_release_sbom.py

printf '%s\n' '== Evidence verifier I/O and reconstruction =='
sed -n '55,155p' src/egressweave/release_evidence.py
sed -n '470,735p' src/egressweave/release_evidence.py

printf '%s\n' '== Documentation and changelog =='
sed -n '1,240p' docs/release-evidence-preparation.md
sed -n '1,260p' docs/release.md
sed -n '1,120p' CHANGELOG.md

printf '%s\n' '== Targeted source locations =='
rg -n -C 6 \
  '_select_distributions|_require_distribution_preflight|_load_attestable_generator|build_attestable_sbom|_sha256_file|_write_private_file|build_evidence_manifest|write_evidence_manifest|_require_post_publication_state|ZipFile|tarfile\.open|_wheel_metadata|_sdist_metadata|_require_open_regular_file|_require_stable_read' \
  scripts/ci/prepare_release_evidence.py \
  scripts/ci/generate_attestable_release_sbom.py \
  scripts/ci/generate_release_sbom.py \
  src/egressweave/release_evidence.py

printf '%s\n' '== Exact range: added imports and effectful API calls =='
git diff --unified=0 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py \
  | rg -n -C 2 \
  '^\+.*\b(import|from|open|os\.open|chmod|mkdir|unlink|rmtree|replace|rename|subprocess|requests|urllib|socket|http|oidc|credential|token|secret|sign|attest|publish|git)\b' || true

Length of output: 130537


@seonghobae I completed a static review of exact head fb54b615cbc69ef92c3ac787db1f3faafbc2cba9 against exact stacked base 6a8f57c29c9ebb561c771829ba75501ba9eb8.

I found one high-severity issue.

  • High — Bind each preflighted distribution to the archive parser. scripts/ci/prepare_release_evidence.py preflights metadata and compressed size by pathname in _require_distribution_preflight() at Line 124. It then passes those mutable pathnames to generator.build_attestable_sbom() at Line 300. The delegated foundation generator opens the path again with zipfile.ZipFile(path) or tarfile.open(path, mode="r:gz"). A concurrent local writer can replace a valid preflighted archive with an oversized regular file that has the same canonical filename after preflight and before parser open. The ZIP or tar parser can process that replacement before later descriptor-bound hashing and final verification reject it. This bypasses the stated finite pre-parser trust boundary. Open each archive through a no-follow descriptor, verify regular-file identity and the byte limit immediately before parsing, and parse that bound descriptor or an immutable verified snapshot. Add a regression that replaces an archive after preflight and proves that the parser does not receive the replacement.

The merge topology matches the requested stack-sync claim. The requested head has first parent 421c0975cdabbc24cb4c42a9bb11e202cd33b0a4 and second parent 6a8f57c29c9ebb561c771829ba75501ba9eb8. Relative to its first parent, it imports only the deterministic strict-JSON parser-recursion test.

The diff against the requested base contains the intended five files only.

The static review found no added direct workflow, credential, permission, network, signing, attestation, release, tag, ref, repository-write, OIDC, or publication behavior.

The implementation otherwise matches the reviewed claims for exact wheel/sdist selection, version binding, deterministic CycloneDX 1.7 output, canonical source identity, filename-sorted checksums, exclusive owner-only output creation, external handoff storage, post-publication reconstruction, failure guidance, non-provenance and no-SLSA boundaries, APA-style references, and changelog wording.

I did not approve, merge, mark ready, rebase, retarget, release, or publish this pull request.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Apply only the bounded CHANGELOG completion to exact current head c90c7f6962329a0012c556bfbcee04b0711010cd on branch release/sealed-evidence-preparation.

The test-first parser-binding repair is already implemented and documented. Modify only CHANGELOG.md:

  • under [Unreleased]Security, add one concise entry stating that each preflighted wheel/source distribution is rebound through a no-follow descriptor to its exact device/inode/size identity, copied with a finite byte ceiling into a fresh owner-only parser-only snapshot, and that ZIP/tar parsers never receive the mutable caller-controlled pathname; post-preflight path replacement therefore fails before parser execution, while later hashing and complete-set verification remain defense in depth;
  • do not imply immutable local storage, hosted provenance, attestation, or a SLSA Build level;
  • do not bump the version or alter any existing release entry.

Do not modify scripts, tests, documentation, .github, workflows, dependencies, permissions, credentials, protected refs, review-agent identities, release/tag/publication behavior, or any other path. Stop without writing if the exact head is no longer c90c7f6962329a0012c556bfbcee04b0711010cd. Do not rebase, retarget, merge, mark ready, enable auto-merge, release, or publish.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Review exact current head 961abb78b9df1fd3dba0dd23582c8379d845556c. Treat prior findings and reviews on earlier heads as stale unless they remain reproducible on this exact tree. Pay particular attention to the no-follow device/inode/size binding, bounded private parser snapshots, post-preflight path replacement, stable fail-closed errors, cleanup semantics, and preservation of later artifact/SBOM/checksum verification. Do not approve or report success for a different head.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Perform a read-only exact-head review of 961abb78b9df1fd3dba0dd23582c8379d845556c for PR #64. Do not modify any file or ref.

Reassess the earlier blocking finding that mutable distribution pathnames could be replaced after preflight and reach ZIP/tar parsing. Verify the current implementation binds accepted device/inode/size through no-follow descriptors, creates finite owner-only parser-only snapshots, delegates parsing only to those snapshots, refuses replacement before parser execution, preserves stable fail-closed behavior and complete later hashing/SBOM/checksum verification, and accurately documents residual mutable-storage and non-provenance boundaries. Also inspect all five changed files for new correctness, security, resource-bound, portability, cleanup, API, documentation, and coverage issues.

Anchor every finding and any formal review outcome to exact head 961abb78b9df1fd3dba0dd23582c8379d845556c. Do not approve, request changes, or claim checks for another head. Do not merge, mark ready, rebase, retarget, release, publish, or change branch state.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='6a8f57c29c9ebb561c771829ba75501ba9a91eb8'
head='961abb78b9df1fd3dba0dd23582c8379d845556c'

printf '%s\n' '== Exact commit and topology =='
git rev-parse "${base}^{commit}"
git rev-parse "${head}^{commit}"
git merge-base --is-ancestor "$base" "$head" && echo 'base_is_ancestor=true'
git show -s --format='head=%H%nparents=%P%nsubject=%s' "$head"

printf '%s\n' '== Exact base-to-head changed files =='
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"

printf '%s\n' '== Target file outlines =='
ast-grep outline scripts/ci/prepare_release_evidence.py --items all
ast-grep outline tests/test_prepare_release_evidence.py --items all
ast-grep outline scripts/ci/generate_attestable_release_sbom.py --items all || true
ast-grep outline scripts/ci/generate_release_sbom.py --items all || true
ast-grep outline src/egressweave/release_evidence.py --items all || true

printf '%s\n' '== Preparer and focused tests =='
nl -ba scripts/ci/prepare_release_evidence.py | sed -n '1,460p'
rg -n -C 12 \
  'preflight|snapshot|replace|rename|descriptor|inode|device|MAX_DISTRIBUTION_BYTES|_load_attestable_generator|build_attestable_sbom|cleanup|unlink|rmtree|handoff|unsafe|bound' \
  tests/test_prepare_release_evidence.py

printf '%s\n' '== Parser and verifier interfaces =='
rg -n -C 10 \
  '^(def |class )|build_attestable_sbom|build_sbom|ZipFile|tarfile\.open|open\(|os\.open|O_NOFOLLOW|O_EXCL|fstat\(|lstat\(|sha256|MAX_|reconstruct|post_publication|manifest|member' \
  scripts/ci/generate_attestable_release_sbom.py \
  scripts/ci/generate_release_sbom.py \
  src/egressweave/release_evidence.py

printf '%s\n' '== Full requested diff =='
git diff --find-renames --find-copies --unified=80 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py \
  tests/test_prepare_release_evidence.py \
  docs/release-evidence-preparation.md \
  docs/release.md \
  CHANGELOG.md

printf '%s\n' '== Added external-effect indicators =='
git diff --unified=0 "$base" "$head" | rg -n -i -C 2 \
  '^\+.*\b(https?://|urllib|requests|socket|subprocess|os\.system|popen|oidc|credential|token|secret|sign|attest|publish|git\s+(tag|push|commit|checkout|reset)|workflow|\.github|release|ref)\b' || true

printf '%s\n' '== Current documentation claims =='
rg -n -C 5 \
  'snapshot|preflight|parser|replacement|SLSA|provenance|CycloneDX|SOURCE_IDENTITY|SHA256SUMS|handoff|References|Unreleased' \
  docs/release-evidence-preparation.md docs/release.md CHANGELOG.md

Length of output: 13359


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='6a8f57c29c9ebb561c771829ba75501ba9a91eb8'
head='961abb78b9df1fd3dba0dd23582c8379d845556c'

show_lines() {
  file="$1"
  start="$2"
  end="$3"
  printf '\n== %s:%s-%s ==\n' "$file" "$start" "$end"
  sed -n "${start},${end}p" "$file" | awk -v n="$start" '{printf "%5d  %s\n", n++, $0}'
}

show_lines scripts/ci/prepare_release_evidence.py 1 520
show_lines tests/test_prepare_release_evidence.py 1 360
show_lines scripts/ci/generate_attestable_release_sbom.py 150 225
show_lines scripts/ci/generate_release_sbom.py 75 165
show_lines scripts/ci/generate_release_sbom.py 360 500
show_lines src/egressweave/release_evidence.py 55 155
show_lines src/egressweave/release_evidence.py 470 735

printf '%s\n' '== Exact requested diff =='
git diff --find-renames --find-copies --unified=100 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py \
  tests/test_prepare_release_evidence.py \
  docs/release-evidence-preparation.md \
  docs/release.md \
  CHANGELOG.md

printf '%s\n' '== Call sites: selected distributions, snapshots, and parser inputs =='
rg -n -C 7 \
  '_select_distributions\(|_require_distribution_preflight\(|_snapshot_distribution\(|_load_attestable_generator\(|build_attestable_sbom\(|_sha256_file\(|build_evidence_manifest\(|write_evidence_manifest\(' \
  scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py

printf '%s\n' '== Documentation and changelog =='
sed -n '1,240p' docs/release-evidence-preparation.md
sed -n '1,300p' docs/release.md
sed -n '1,100p' CHANGELOG.md

printf '%s\n' '== Changed code external-effect scan =='
git diff --unified=0 "$base" "$head" -- \
  scripts/ci/prepare_release_evidence.py tests/test_prepare_release_evidence.py \
  | rg -n -i -C 3 \
  '^\+.*\b(urllib|requests|socket|subprocess|os\.system|popen|oidc|credential|token|secret|sign|attest|publish|git\s+(tag|push|commit|checkout|reset)|workflow|\.github)\b' || true

Length of output: 175219


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected='961abb78b9df1fd3dba0dd23582c8379d845556c'

printf '%s\n' '== Checked-out head =='
actual="$(git rev-parse HEAD)"
printf 'expected=%s\nactual=%s\n' "$expected" "$actual"
test "$actual" = "$expected"
printf '%s\n' 'checkout_matches_expected=true'

printf '%s\n' '== PR `#64` head =='
gh api repos/ContextualWisdomLab/EgressWeave/pulls/64 \
  --jq '.head.sha | "pr_head=\(.)"' \
  | tee /tmp/pr-head.txt
test "$(sed 's/^pr_head=//' /tmp/pr-head.txt)" = "$expected"
printf '%s\n' 'pr_head_matches_expected=true'

Length of output: 1064


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected='961abb78b9df1fd3dba0dd23582c8379d845556c'
actual="$(gh api repos/ContextualWisdomLab/EgressWeave/pulls/64 --jq '.head.sha')"
printf 'expected=%s\npr_head=%s\n' "$expected" "$actual"
test "$actual" = "$expected"
printf '%s\n' 'pr_head_matches_expected=true'

Length of output: 565


@seonghobae I completed the static review of PR #64 at exact head 961abb78b9df1fd3dba0dd23582c8379d845556c. The checkout HEAD and the GitHub PR head both match this SHA.

I found no new issue in the reviewed scope.

The earlier parser-path finding is not reproducible on this head. The preparer now:

  • preflights the selected wheel and source distribution;
  • binds each accepted input to device, inode, and finite size;
  • opens the input with no-follow flags;
  • validates descriptor and pathname identity before and after the bounded copy;
  • creates owner-only private snapshots; and
  • passes only wheel_snapshot and sdist_snapshot to build_attestable_sbom().

The replacement regression verifies that a replacement after preflight reaches neither the generator nor the parser. It also verifies that the preparer creates no generated evidence or handoff.

The implementation retains later bounded descriptor/path hashing, archive and SBOM validation, checksum binding, exclusive owner-only output creation, and independent post-publication reconstruction. The failure and retry guidance correctly treats partial local output as untrusted. The documentation preserves the non-provenance and no-SLSA-Build-level boundary. The reviewed diff adds no network, credential, workflow, repository-write, OIDC, signing, attestation, tag, release, or publication behavior.

I did not approve, merge, rebase, retarget, publish, or release the pull request.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant